// Copyright (C) 2025 Kumo inc.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef ROTHAR_PEGTL_SRC_TEST_PEGTL_TEST_HPP
#define ROTHAR_PEGTL_SRC_TEST_PEGTL_TEST_HPP

#include <cstddef>
#include <exception>
#include <iostream>

#include <rothar/pegtl.hpp>

namespace rothar
{
   std::size_t failed = 0;

}  // namespace rothar

#define ROTHAR_TEST_STRINGIZE_INTERNAL( ... ) #__VA_ARGS__
#define ROTHAR_TEST_STRINGIZE( ... ) ROTHAR_TEST_STRINGIZE_INTERNAL( __VA_ARGS__ )

#define ROTHAR_TEST_LINE ROTHAR_TEST_STRINGIZE( __LINE__ )

#define ROTHAR_PEGTL_TEST_UNWRAP( ... ) __VA_ARGS__

#define ROTHAR_PEGTL_TEST_FAILED( MeSSaGe )                   \
   do {                                                    \
      std::cerr << "pegtl: unit test failed for [ "        \
                << rothar::demangle< Rule >() \
                << " ] "                                   \
                << ROTHAR_PEGTL_TEST_UNWRAP( MeSSaGe )        \
                << " in line [ "                           \
                << line                                    \
                << " ] file [ "                            \
                << file << " ]"                            \
                << std::endl;                              \
      ++rothar::failed;                       \
   } while( false )

#define ROTHAR_PEGTL_TEST_ASSERT( ... )               \
   do {                                            \
      if( !( __VA_ARGS__ ) ) {                     \
         std::cerr << "pegtl: unit test assert [ " \
                   << ( #__VA_ARGS__ )             \
                   << " ] failed in line [ "       \
                   << __LINE__                     \
                   << " ] file [ "                 \
                   << __FILE__ << " ]"             \
                   << std::endl;                   \
         ++rothar::failed;            \
      }                                            \
   } while( false )

#define ROTHAR_PEGTL_TEST_THROWS( ... )                \
   do {                                             \
      try {                                         \
         __VA_ARGS__;                               \
         std::cerr << "pegtl: unit test [ "         \
                   << ( #__VA_ARGS__ )              \
                   << " ] did not throw in line [ " \
                   << __LINE__                      \
                   << " ] file [ "                  \
                   << __FILE__ << " ]"              \
                   << std::endl;                    \
         ++rothar::failed;             \
      }                                             \
      catch( ... ) {                                \
      }                                             \
   } while( false )

#define ROTHAR_PEGTL_TEST_UNREACHABLE                                                                                              \
   do {                                                                                                                         \
      std::cerr << "Code should be unreachable in " << __FUNCTION__ << " (" << __FILE__ << ':' << __LINE__ << ')' << std::endl; \
      std::terminate();                                                                                                         \
   } while( false )

#endif
